import { execSync, execFileSync, ExecFileSyncOptions } from 'child_process';

/**
 * execute args
 */
export class ShellArgs {
    /**
     * exclude empty line
     */
    excludeEmptyLine: boolean = true;

    /**
     * trim line start and end
     */
    trimLine: boolean = true;
}

/**
 * shell interface
 */
export interface IShell {
    /**
     * execute command
     * @param command command
     * @param ExecuteArgs execute args
     */
    execSync(command: string, args?: ShellArgs): string[];

    /**
     * execute target
     * @param target target path
     * @param ExecuteArgs execute args
     * @param options options
     */
    execSyncTarget(target: string, args?: ShellArgs, options?: ExecFileSyncOptions): string[];
}

/**
 * shell implementation
 */
class ShellImpl implements IShell {
    /**
     * 执行同步命令
     * @param command 命令
     * @param args 执行参数
     * @returns 输出字符串数组
     */
    execSync(command: string, args?: ShellArgs): string[] {
        let lines = execSync(command).toString("utf-8").split(/\r?\n/);
        if (args) {
            if (args.excludeEmptyLine) {
                lines = lines.filter(line => !!line);
            }
            if (args.trimLine) {
                lines = lines.map(lines => lines.trim())
            }
        }
        return lines;
    }

    execSyncTarget(target: string, args?: ShellArgs, options?: ExecFileSyncOptions): string[] {
        let lines = execFileSync(target, options).toString('utf-8').split(/\r?\n/);
        if (args) {
            if (args.excludeEmptyLine) {
                lines = lines.filter(line => !!line);
            }
            if (args.trimLine) {
                lines = lines.map(lines => lines.trim())
            }
        }
        return lines;
    }
}

/**
 * shell wrapper
 */
export class Shell {
    private static _impl: IShell = new ShellImpl();

    /**
     * execute command
     * @param command commanda
     * @param formatArgs output format args
     */
    public static execSync(command: string, args?: ShellArgs): string[] {
        return this._impl.execSync(command, args);
    }

    /**
     * execute target
     * @param target target path
     * @param args args
     * @param options options
     */
    public static execSyncTarget(target: string, args?: ShellArgs, options?: ExecFileSyncOptions): string[] {
        return this._impl.execSyncTarget(target, args, options);
    }
}